package com.wmada.toolkit.rest.utils;

import com.wmada.toolkit.rest.UserAgent;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;

/**
 * The type Url utils.
 *
 * @author will.ma
 * @date 2016 /8/16
 */
@SuppressWarnings("unused")
public class UrlUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(UrlUtils.class);

    private static URL parse(String url) {
        if (StringUtils.isBlank(url)) {
            return null;
        }
        try {
            return new URL(url);
        } catch (MalformedURLException e) {
            return null;
        }
    }

    /**
     * Validate boolean.
     *
     * @param url the url
     * @return the boolean
     */
    public static boolean validate(String url) {
        return parse(url) != null;
    }

    /**
     * Gets domain.
     *
     * @param url the url
     * @return the domain
     */
    public static String getDomain(String url) {
        URL u = parse(url);
        if (u != null) {
            return u.getHost();
        } else {
            return "";
        }
    }

    /**
     * Gets host.
     *
     * @param url the url
     * @return the host
     */
    public static String getHost(String url) {
        URL u = parse(url);
        if (u != null) {
            return u.getProtocol() + "://" + u.getHost() + (u.getPort() == u.getDefaultPort() || u.getPort() == -1 ? "" : ":" + u.getPort());
        } else {
            return "";
        }
    }

    /**
     * Gets port.
     *
     * @param url the url
     * @return the port
     */
    public static Integer getPort(String url) {
        URL u = parse(url);
        if (u != null) {
            int port = u.getPort();
            if (port != -1) {
                return port;
            } else {
                return u.getDefaultPort();
            }
        } else {
            return -1;
        }
    }

    /**
     * Gets path.
     *
     * @param url the url
     * @return the path
     */
    public static String getPath(String url) {
        URL u = parse(url);
        if (u != null) {
            return u.getPath();
        } else {
            return "";
        }
    }

    /**
     * Gets protocol.
     *
     * @param url the url
     * @return the protocol
     */
    public static String getProtocol(String url) {
        URL u = parse(url);
        if (u != null) {
            return u.getProtocol();
        } else {
            return "";
        }
    }

    /**
     * Gets query.
     *
     * @param url the url
     * @return the query
     */
    public static String getQuery(String url) {
        URL u = parse(url);
        if (u != null) {
            return u.getQuery();
        } else {
            return "";
        }
    }

    /**
     * Gets params.
     *
     * @param url the url
     * @return the params
     */
    public static LinkedHashMap<String, ArrayList<String>> getParams(String url) {
        LinkedHashMap<String, ArrayList<String>> paramsMap = new LinkedHashMap<>();
        String                                   params    = getQuery(url);
        if (StringUtils.isNotBlank(params)) {
            String[] paramsArray = params.split("&");
            for (String param : paramsArray) {
                int pos = param.indexOf('=');
                if (pos == -1) {
                    continue;
                }
                try {
                    String            key   = param.substring(0, pos);
                    String            value = URLDecoder.decode(param.substring(pos + 1), "UTF-8");
                    ArrayList<String> list  = paramsMap.computeIfAbsent(key, k -> new ArrayList<>());
                    list.add(value);
                } catch (UnsupportedEncodingException e) {
                    LOGGER.warn("解析输入参数失败：" + param, e);
                }
            }
        }
        return paramsMap;
    }

    /**
     * Gets absolute path.
     *
     * @param relativePath the relative path
     * @param originPath   the origin path
     * @return the absolute path
     */
    public static String getAbsolutePath(String relativePath, String originPath) {
        URL url = getAbsoluteUrl(relativePath, originPath);
        if (url != null) {
            return url.toString();
        } else {
            return null;
        }
    }

    private static URL getAbsoluteUrl(String relativePath, String originPath) {
        if (StringUtils.isBlank(relativePath)) {
            return null;
        }
        URL originUrl = parse(originPath);
        if (originUrl == null) {
            return parse(relativePath);
        } else {
            try {
                return new URL(originUrl, relativePath);
            } catch (MalformedURLException e) {
                return null;
            }
        }
    }

    /**
     * Encode string.
     *
     * @param param the param
     * @return the string
     */
    public static String encode(String param) {
        try {
            return URLEncoder.encode(param, "utf-8");
        } catch (Exception e) {
            return param;
        }
    }

    public static String decode(String param) {
        try {
            return URLDecoder.decode(param, "utf-8");
        } catch (UnsupportedEncodingException e) {
            return param;
        }
    }

    /**
     * Encode file name string.
     *
     * @param filename  the filename
     * @param userAgent the user agent
     * @return the string
     */
    public static String encodeFileName(String filename, String userAgent) {
        try {
            UserAgent agent = UserAgent.getUserAgent(userAgent);
            if (agent == null || agent.isUnknown() || agent.isIE()) {// google,火狐浏览器
                filename = URLEncoder.encode(filename, "UTF8");// 其他浏览器
            } else {
                filename = "\"" + filename + "\"";
                filename = new String(filename.getBytes(), "ISO8859-1");
            }
        } catch (UnsupportedEncodingException e) {
            LOGGER.warn("", e);
        }
        return filename;
    }

    /**
     * Generate path string.
     *
     * @param path    the path
     * @param paramKv the param kv
     * @return the string
     */
    public static String generatePath(String path, String... paramKv) {
        List<String> params = new ArrayList<>(Arrays.asList(paramKv));
        if (params.size() % 2 != 0) {
            params.add("");
        }
        List<String> pairs = new ArrayList<>();
        for (int i = 0; i < params.size() / 2; i++) {
            pairs.add(params.get(2 * i) + "=" + UrlUtils.encode(params.get(2 * i + 1)));
        }
        return (path.contains("?") ? (path + "&") : (path + "?")) + StringUtils.join(pairs, "&");
    }

    /**
     * Generate path string.
     *
     * @param path    the path
     * @param paramKv the param kv
     * @return the string
     */
    public static String generatePath(String path, Map<String, Object> paramKv) {
        List<String> pairs = new ArrayList<>();
        for (Map.Entry<String, Object> param : paramKv.entrySet()) {
            pairs.add(param.getKey() + "=" + (param.getValue() != null ? UrlUtils.encode(param.getValue().toString()) : ""));
        }
        return (path.contains("?") ? (path + "&") : (path + "?")) + StringUtils.join(pairs, "&");
    }

}
